#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>

/*#include <glib/gi18n-lib.h>*/
#include <glib/gkeyfile.h>
#include <gtk/gtk.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libnautilus-extension/nautilus-extension-types.h>
#include <libnautilus-extension/nautilus-info-provider.h>
#include <libnautilus-extension/nautilus-menu-provider.h>

typedef struct {
    GObject parent;
} SVNTilus;

typedef struct {
    GObjectClass parent_class;
} SVNTilusClass;

static GType svntilus_type;

static GList* 
svntilus_get_file_items (NautilusMenuProvider *provider,
                  GtkWidget *window,
                  GList *files);

static void
svntilus_context_menu_activate (NautilusMenuItem *item,
          gpointer user_data);

static NautilusOperationResult
svntilus_update_file_info (NautilusInfoProvider *provider,
			   NautilusFileInfo *file,
			   GClosure *update_complete,
			   NautilusOperationHandle **handle);

static void
svntilus_init (SVNTilus *self)
{
}

static void
svntilus_class_init (SVNTilusClass *class)
{
}

static void
svntilus_info_provider_iface_init (NautilusInfoProviderIface *iface)
{
  iface->update_file_info = svntilus_update_file_info;
}

static void
svntilus_menu_provider_iface_init (NautilusMenuProviderIface *iface)
{
    iface->get_file_items = svntilus_get_file_items;
}


static void
svntilus_register_type (GTypeModule *module)
{
  static const GTypeInfo info = {
    sizeof (SVNTilusClass),
    (GBaseInitFunc) NULL,
    (GBaseFinalizeFunc) NULL,
    (GClassInitFunc) svntilus_class_init,
    NULL,
    NULL,
    sizeof (SVNTilus),
    0,
    NULL,
  };

  static const GInterfaceInfo info_provider_iface_info = {
    (GInterfaceInitFunc) svntilus_info_provider_iface_init,
    NULL,
    NULL
  };

   static const GInterfaceInfo menu_provider_iface_info = {
        (GInterfaceInitFunc)svntilus_menu_provider_iface_init,
        NULL, NULL
    };

  svntilus_type = g_type_module_register_type (module,
					       G_TYPE_OBJECT,
					       "SVNTilusExtension",
					       &info, 0);

  g_type_module_add_interface (module,
			       svntilus_type,
			       NAUTILUS_TYPE_INFO_PROVIDER,
			       &info_provider_iface_info);

  g_type_module_add_interface (module,
			       svntilus_type,
			       NAUTILUS_TYPE_MENU_PROVIDER,
			       &menu_provider_iface_info);

}

GType
svntilus_get_type (void)
{
  return svntilus_type;
}

static GType provider_types[1];

void
nautilus_module_initialize (GTypeModule  *module)
{
  svntilus_register_type (module);

  provider_types[0] = svntilus_get_type ();
}

void
nautilus_module_shutdown (void)
{
}

void
nautilus_module_list_types (const GType **types,
			    int *num_types)
{
  *types = provider_types;
  *num_types = G_N_ELEMENTS (provider_types);
}


/* actual code */
static gboolean
is_svnrepo (NautilusFileInfo *file)
{
        GnomeVFSURI *uri;

        gchar *text_uri = nautilus_file_info_get_uri (file);
        uri = gnome_vfs_uri_new (text_uri);
        if (gnome_vfs_uri_is_local (uri) && nautilus_file_info_is_directory (file))       
            {
              const gchar *dir_path = gnome_vfs_uri_get_path (uri);
              gchar *full_path = g_strdup_printf ("%s/.svn", dir_path);
              if (g_file_test (full_path, G_FILE_TEST_EXISTS)) {
              g_free (full_path);
              g_free (uri);
              return TRUE;
            } 
        }   
        g_free(uri);
        return FALSE;
}



static GList *
svntilus_get_file_items (NautilusMenuProvider *provider,
                  GtkWidget *window,
                  GList *files)
{
    NautilusMenuItem *item;
    GList *items = NULL;
    GList *l;
    guint num;
    num = g_list_length (files);
    NautilusFileInfo *file; 

    for (l = files; l != NULL; l = l->next) {
        NautilusFileInfo *file = NAUTILUS_FILE_INFO (l->data);

    if (is_svnrepo(file)) {
        item = nautilus_menu_item_new ("NautilusSVN::Update", "SVN Update",
            ngettext ("Update weee", "SVN Update fooo", num), NULL);
        g_object_set_data_full (G_OBJECT (item), "files", nautilus_file_info_list_copy (files),
                                     (GDestroyNotify) nautilus_file_info_list_free);
        g_signal_connect (item, "activate", G_CALLBACK (svntilus_context_menu_activate), provider);
        items = g_list_append (items, item);
        }
    }
   return items;

}

static void
svntilus_context_menu_activate (NautilusMenuItem *item,
          gpointer user_data)
{

    GList *files, *scan;
    char *uri, *t;
    GString *cmd;

    files = g_object_get_data (G_OBJECT (item), "files");
    g_assert (files != NULL);

    cmd = g_string_new ("svn");
    g_string_append_printf (cmd, " update");

    for (scan = files; scan; scan = scan->next) {
        uri = nautilus_file_info_get_uri ((NautilusFileInfo*)scan->data);
        t = g_shell_quote (uri);
        g_free (uri);

        g_string_append_printf (cmd, " %s", t);
        g_free (t);
    }

    g_print ("EXEC: %s\n", cmd->str);
    g_spawn_command_line_async (cmd->str, NULL);

    g_string_free (cmd, TRUE);


}

static NautilusOperationResult
svntilus_update_file_info (NautilusInfoProvider *provider,
			   NautilusFileInfo *file,
			   GClosure *update_complete,
			   NautilusOperationHandle **handle)
{
    if (is_svnrepo(file)) {
    	nautilus_file_info_add_emblem (file,
				       "debian");
    }
  return NAUTILUS_OPERATION_COMPLETE;
}
